
#include "esp32_base.h"
#include "BluetoothSerial.h"

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#define KEY_MAX_VALUE      2500
#define KEY_PRESS_TIMEOUT  2000

enum KeyStateEnum {
  KeyOff = 0,  // released
  KeyPending,  // in debounce interval
  KeyOn,       // pressed, duration <= pressTimeout
  KeyPressed   // pressed, duration >  pressTimeout
};

const int KEY_VALUE[] = {1, 100, 500, 1000, KEY_MAX_VALUE};
int keyState[5] = {0, 0, 0, 0, 0};
int keyLastVal = KEY_MAX_VALUE;
int keyLastTime = 0;
int keyHandled = 0;

BluetoothSerial sBT;

//========================================================
void ESP32Base::press_btn_cb(press_btn_t press_fn)
{
    _custom_press = press_fn;
}

void ESP32Base::longs_btn_cb(longs_btn_t longs_fn)
{
    _custom_longs = longs_fn;
}

//========================================================
void ESP32Base::smart_cfg()
{
    WiFi.mode(WIFI_STA);
    WiFi.beginSmartConfig();
    while(1)
    {
        Serial.print(".");
        delay(500);
        if (WiFi.smartConfigDone())
        {
            Serial.println(WiFi.localIP());
            break;
        }
    }
}

bool ESP32Base::auto_cfg()
{
    WiFi.begin();
    for (int i = 0; i < 10; i++)
    {
        int ws = WiFi.status();
        if (ws == WL_CONNECTED)
        {
            Serial.println(WiFi.localIP());
            return true;
        }
        delay(1000);
    }
    return false;
}

//========================================================
void ESP32Base::init()
{
    Serial.begin(115200);
    sBT.begin("esp32");
    pinMode(KEY_PIN, INPUT_PULLUP);
    
    if (!auto_cfg()) smart_cfg();    
    // ArduinoOTA.setPort(3232);
    // ArduinoOTA.setHostname("myesp32");
    // ArduinoOTA.begin();
}

//========================================================
void ESP32Base::routine()
{
    if (sBT.available())
    {
        Serial.println(sBT.read());
    }

    key_update();
    //ArduinoOTA.handle();
}

//===================================================
void ESP32Base::key_update() {
  int key = -1;
  unsigned long now = millis();
  unsigned long interval = now - keyLastTime;
  if (interval < 50) return;
  int val = analogRead(KEY_PIN);
  for (int i = 0; i < 5; i++) {
    if (val < KEY_VALUE[i]) {
      key = i;
      break;
    }
  }
  //--------------------------------------------------------
  if (key >= 0) {
    switch (keyState[key]) {
      case KeyOff:
        keyState[key] = KeyPending;
        keyLastTime = now;
        break;
      case KeyPending:
        keyState[key] = KeyOn;
        keyLastTime = now;
        break;
      case KeyOn:
        if (interval > KEY_PRESS_TIMEOUT) {
          keyState[key] = KeyPressed;
          keyLastTime = now;
        }
        break;
      default:
        break;
    }
    //------------------------------------------------------
    if (keyState[key] == KeyPressed) {
      if (!keyHandled) {
        if (_custom_longs != nullptr) _custom_longs(key);
        keyHandled = 1;
      }
    }
  }
  //--------------------------------------------------------
  else if (keyLastVal < KEY_MAX_VALUE) {
    if (!keyHandled) {
      for (int i = 0; i < 5; i++) {
        if (keyState[i] == KeyOn) {
          if (_custom_press != nullptr) _custom_press(i);
          break;
        }
      }
    }
    for (int i = 0; i < 5; i++) {
      keyState[i] = KeyOff;
    }
    keyHandled = 0;
    keyLastTime = 0;
  }
  keyLastVal = val;
}

//=========================================================
